/**
 * @file    hal_log.h
 * @author  Azolla (1228449928@qq.com)
 * @brief   log module header file.
 * @version 0.1
 * @date    2025-04-23
 *
 * @copyright Copyright (c) 2025
 * */
#ifndef INCLUDE_HAL_LOG_H_
#define INCLUDE_HAL_LOG_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "autoconf.h"
#include "type.h"

#if CONFIG_FREERTOS
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
extern SemaphoreHandle_t logMutex; // if (logMutex != NULL) 
#define LOG_LOCK()      if (logMutex) xSemaphoreTake(logMutex, portMAX_DELAY)
#define LOG_UNLOCK()    if (logMutex) xSemaphoreGive(logMutex)
#define LogTimestamp()  (uint32_t)xTaskGetTickCount()
#else 
#define LOG_LOCK()      
#define LOG_UNLOCK()    
#define LogTimestamp()  (uint32_t)(0)
#endif
//=================================================================================================================================
//=================================================================================================================================
#if CONFIG_LOG_COLOR
#define LOG_COLOR_BLACK   "30"
#define LOG_COLOR_RED     "31"
#define LOG_COLOR_GREEN   "32"
#define LOG_COLOR_BROWN   "33"
#define LOG_COLOR_BLUE    "34"
#define LOG_COLOR_PURPLE  "35"
#define LOG_COLOR_CYAN    "36"
#define LOG_BLANK(COLOR)  "\033[5;" COLOR "m"       // 闪烁
#define LOG_COLOR(COLOR)  "\033[0;" COLOR "m"       // 正常
#define LOG_BOLD(COLOR)   "\033[1;" COLOR "m"       // 高亮
#define LOG_RESET_COLOR   "\033[0m"                 // 无
#define LOG_COLOR_ERR     LOG_BLANK(LOG_COLOR_RED)
#define LOG_COLOR_WRN     LOG_BOLD(LOG_COLOR_BROWN)
#define LOG_COLOR_INF     LOG_COLOR(LOG_COLOR_GREEN)
#define LOG_COLOR_DBG     LOG_COLOR(LOG_COLOR_CYAN)
#else
#define LOG_RESET_COLOR
#define LOG_COLOR_ERR
#define LOG_COLOR_WRN
#define LOG_COLOR_INF
#define LOG_COLOR_DBG
#endif

#define LOG_FORMAT(letter, format)          LOG_COLOR_ ## letter #letter " (%ld) %s: " format LOG_RESET_COLOR "\r\n"
#define LOG_EARLY(tag, format, letter, ...) do { \
    LOG_LOCK(); \
    printf(LOG_FORMAT(letter, format), LogTimestamp(), tag, ##__VA_ARGS__); \
    LOG_UNLOCK(); \
} while(0)
#define LOG_ERR(tag, format, ...)           LOG_EARLY(tag, format, ERR, ##__VA_ARGS__)
#define LOG_WRN(tag, format, ...)           LOG_EARLY(tag, format, WRN, ##__VA_ARGS__)
#define LOG_INF(tag, format, ...)           LOG_EARLY(tag, format, INF, ##__VA_ARGS__)
#define LOG_DGB(tag, format, ...)           LOG_EARLY(tag, format, DBG, ##__VA_ARGS__)

#define ADDRFMT      "%02X"
#define ADDRSTR      ""MACFMT""MACFMT""MACFMT""MACFMT""MACFMT""MACFMT""
#define ADDR2STR(a)  (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define LOG_ADDR(tag, addr)      LOG_INF(tag, ADDRSTR, ADDR2STR(addr))

#define MACFMT      "%02X"
#define MACSTR      ""MACFMT":"MACFMT":"MACFMT":"MACFMT":"MACFMT":"MACFMT""
#define MAC2STR(a)  (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
#define LOG_MAC(tag, addr)       LOG_INF(tag, MACSTR,  MAC2STR(addr))

#define ADDR_MEMCPY_SWAP(addr_out, addr_in)  for (uint8_t i = 0; i < 6; i++) {  *((uint8_t *)(addr_out) + i) = ((uint8_t *)(addr_in))[5 - i]; }

#define LOG_ASSERT( expression )  do { \
    if (expression) { \
        LOGE("Assert errno[%d] at File: %s, Func: %s, Line: %d", expression, __FILE__, __FUNCTION__, __LINE__); \
        assert(expression); while(1); \
    } \
} while(0)

#define LOG_ASSERT_NO_MSG( expression )  do { \
    if (!(expression)) { \
        LOG_ERR("ASSERT", "Assert errno[%d] at File: %s, Func: %s, Line: %d", expression, __FILE__, __FUNCTION__, __LINE__); \
    } \
} while(0)

#define LOG_ASSERT_MSG( expression, msg )  do { \
    if (!(expression)) { \
        LOG_ERR("ASSERT", "Assert: %s, at File: %s, Func: %s, Line: %d", msg, __FILE__, __FUNCTION__, __LINE__); \
    } \
} while(0)

#define LOG_HEX(tag, hex, len)   do { \
    printf("HEX (%d) %s: ", LogTimestamp(), tag); \
    for (uint16_t i = 0; i < len; i++) \
    printf("%02X ", *((uint8_t *)(hex) + i)); \
    printf("| len = %d\r\n", len); \
} while(0)

#define LOG_HEX16(tag, hex, len)   do { \
    printf("HEX (%d) %s: ", LogTimestamp(), tag); \
    for (uint16_t i = 0; i < len; i++) \
    printf("%04X ", *((uint16_t *)(hex) + i)); \
    printf("| len = %d\r\n", len); \
} while(0)

#define LOG_DEC(tag, var, dec, len)   do { \
    printf("DEC (%d) %s: ", LogTimestamp(), tag); \
    for (uint16_t i = 0; i < len; i++) \
    printf("%d ", *((var *)(dec) + i)); \
    printf("| len = %d\r\n", len); \
} while(0)

#define LGO_WAIT_DONE() do { \
    R8_WDOG_COUNT = 0x00;  \
    while ((R8_UART1_LSR & RB_LSR_TX_ALL_EMP) == 0); \
} while(0)

#define LOG_DUMP2HEX   LOG_HEX
//=====================================================================
//=====================================================================
#define LOG_LEVEL_NONE 0  // 无效等级
#define LOG_LEVEL_ERR  1  // 错误等级
#define LOG_LEVEL_WRN  2  // 警告等级
#define LOG_LEVEL_INF  3  // 信息等级
#define LOG_LEVEL_DBG  4  // 调试等级

#if LOG_SET_LEVEL >= LOG_LEVEL_DBG
#define LOGD(fmt, ...)  LOG_DGB(TAG, fmt, ##__VA_ARGS__)
#else
#define LOGD(fmt, ...)  (void)0
#endif

#if LOG_SET_LEVEL >= LOG_LEVEL_INF
#define LOGI(fmt, ...)   LOG_INF(TAG, fmt, ##__VA_ARGS__)
#else
#define LOGI(fmt, ...)   (void)0
#endif

#if LOG_SET_LEVEL >= LOG_LEVEL_WRN
#define LOGW(fmt, ...)   LOG_WRN(TAG, fmt, ##__VA_ARGS__)
#else
#define LOGW(fmt, ...)   (void)0
#endif

#if LOG_SET_LEVEL >= LOG_LEVEL_ERR
#define LOGE(fmt, ...)   LOG_ERR(TAG, fmt, ##__VA_ARGS__)
#else
#define LOGE(fmt, ...)   (void)0
#endif

#ifdef __cplusplus
}
#endif

#endif /* INCLUDE_HAL_LOG_H_ */
